(function(angular) {
  'use strict';
  angular.module('fs.keyDown', ['fs.storage']).factory('keyDownService', [
    '$filter',
    'storageService',
    function($filter, storageService) {
      //=================================================
      //      On key down                             ===
      //=================================================
      //the formatManager should get from back.
      var formatInfo = storageService.getFormatInfo() || {};
      var decimalSeparator = formatInfo.decimalSeparator || '.';
      var FORMAT_MANAGER = {
        decimalSeparator: decimalSeparator
      };

      /**
       * Coder can type back space, delete, home and end etc.
       * @return boolean. when key which is being pressed is one of the following keys, return true.
       */
      function baseKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        if (evt.ctrlKey) {
          return (
            keyCode == 67 || // ^C
            keyCode == 86 || // ^V
            keyCode == 88
          ); // ^X
        } else {
          return (
            keyCode == 8 || // back space
            keyCode == 46 || // delete
            keyCode == 35 || // home
            keyCode == 36 || // end
            keyCode == 37 || // <-
            keyCode == 38 || // cursor up
            keyCode == 39 || // ->
            keyCode == 40 || // cursor down
            keyCode == 9
          ); // tab
        }
      }

      /**
       * Coder can enter.
       * @return boolean. when key which pressed is enter, return true.
       */
      function enterKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        return keyCode == 13; // enter
      }

      /**
       * type dot.
       * @return boolean. when key which pressed is dot, return true.
       */
      function dotKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        return (
          keyCode == 110 || // '.'
          (!evt.shiftKey && keyCode == 190)
        ); // '.' on standard 102 keyboard
      }

      /**
       * type decimal separator
       * @return boolean. when key which pressed is decimal separator, return true.
       */
      function decimalSeparatorKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var mark;
        if (evt.shiftKey) {
          var shiftKey = {
            '188': '<',
            '190': '>',
            '191': '?',
            '48': ')',
            '49': '!',
            '50': '@',
            '51': '#',
            '52': '$',
            '53': '%',
            '54': '^',
            '55': '&',
            '56': '*',
            '57': '(',
            '189': '_',
            '187': '+',
            '192': '~',
            '219': '{',
            '221': '}',
            '186': ':',
            '222': '"',
            '173': '_'
          };
          mark = shiftKey[keyCode];
        } else {
          var normalKey = {
            '188': ',',
            '110': FORMAT_MANAGER.decimalSeparator,
            '190': '.', //110 is in number keybord
            '32': ' ',
            '189': '-',
            '187': '=',
            '49': '`',
            '219': '[',
            '221': ']',
            '186': ';',
            '222': "'",
            '173': '_'
          };
          mark = normalKey[keyCode];
        }
        if (keyCode == 110) {
          (evt.srcElement || evt.target).value = (evt.srcElement || evt.target).value + FORMAT_MANAGER.decimalSeparator;
          evt.returnValue = false;
          if (evt.preventDefault) {
            evt.preventDefault();
          }
        }
        return FORMAT_MANAGER.decimalSeparator == mark;
      }

      /**
       * type letters.
       * @param
       * @return boolean
       */
      function letterKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        return keyCode >= 65 && keyCode <= 96; // a - z;A - Z
      }

      /**
       * type number.
       * @return boolean
       */
      function numKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        return (
          (!evt.shiftKey && keyCode >= 48 && keyCode <= 57) || // 0 - 9
          (keyCode >= 96 && keyCode <= 105)
        ); // 0 - 9 on standard 102 Keyboard
      }

      /**
       * type ID includes letters, numbers, dash and underscore.
       * 0 - 9; a - z; A - Z; -; _;
       *
       * @param
       * @return boolean
       */
      function idKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        isValidKey = letterKeyDown() || numKeyDown(); // 0 - 9; a - z; A - Z
        if (isValidKey) {
          return isValidKey;
        }
        return (
          keyCode == 109 || // '-' on standard 102 keyboard
          keyCode == 173 || // '-' or '_' in firefox broswer
          keyCode == 189
        ); // '-' or '_' in other broswer
      }

      /**
       * type ID includes numbers, letters and underscore.
       * 0 - 9; a - z; A - Z; _;
       *
       * @param
       * @return boolean
       */
      function id2KeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        isValidKey = letterKeyDown() || numKeyDown(); // 0 - 9; a - z; A - Z
        if (isValidKey) {
          return isValidKey;
        }
        return (
          (evt.shiftKey && keyCode == 173) || // '_' in firefox broswer
          (evt.shiftKey && keyCode == 189)
        ); // '_' in other broswer
      }

      /**
       * type ID includes numbers, letters and dash.
       * 0 - 9; a - z; A - Z; ,; -;
       *
       * @param
       * @return boolean
       */
      function id3KeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        isValidKey = letterKeyDown() || numKeyDown(); // 0 - 9; a - z; A - Z
        if (isValidKey) {
          return isValidKey;
        }
        return (
          keyCode == 109 || // '-' on standard 102 keyboard
          (!evt.shiftKey && keyCode == 173) || // only '-' in firefox broswer
          (!evt.shiftKey && keyCode == 189) || // only '-' in other broswer
          keyCode == 188
        ); // ','
      }

      /**
       * type ID includes numbers, letters, dash, underscore, dot andt at.
       * 0 - 9; a - z; A - Z; -; _; .; @;
       *
       * @param
       * @return boolean
       */
      function id4KeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        isValidKey = idKeyDown() || dotKeyDown(); // 0 - 9; a - z; A - Z; -; _; .;
        if (isValidKey) {
          return isValidKey;
        }
        return evt.shiftKey && keyCode == 50; // only '-'
      }

      /**
       * type ID includes numbers and letters.
       * 0 - 9; a - z; A - Z;
       *
       * @param
       * @return boolean
       */
      function id5KeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        return letterKeyDown() || numKeyDown(); // 0 - 9; a - z; A - Z
      }

      /**
       * type ID includes numbers, letters, dash, underscore and space.
       * 0 - 9; a - z; A - Z; -; _; ' ';
       *
       * @param
       * @return boolean
       */
      function id6KeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        return keyCode == 32 || idKeyDown(); // 0 - 9; a - z; A - Z; -; _; ' ';
      }

      /**
       * type class includes letters and dot.
       * a - z; A - Z; .;
       *
       * @param
       * @return boolean
       */
      function classpathKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        return letterKeyDown() || dotKeyDown(); // a - z; A - Z; .;
      }

      /**
       * type float number.
       * @param value
       * @return
       */
      function floatKeyDown(e, value) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        var isValidKey = baseKeyDown(e);
        if (isValidKey) {
          return isValidKey;
        }
        isValidKey = numKeyDown(); // for number
        if (value && value.indexOf(FORMAT_MANAGER.decimalSeparator) != -1) {
          //if value is float
          return isValidKey;
        } else {
          //if value is integer, U can type decimal separator.
          return isValidKey || decimalSeparatorKeyDown();
        }
      }
      function minusKeyDown(e) {
        var evt = window.event || e;
        var keyCode = evt.which ? evt.which : evt.keyCode;
        return (
          keyCode == 109 || // '-' on standard 102 keyboard
          (!evt.shiftKey && keyCode == 173) || // only '-' in firefox broswer
          (!evt.shiftKey && keyCode == 189)
        ); // '-' or '_' in other broswer
      }
      return {
        numKeyDown: numKeyDown,
        idKeyDown: idKeyDown,
        id2KeyDown: id2KeyDown,
        id3KeyDown: id3KeyDown,
        id4KeyDown: id4KeyDown,
        id5KeyDown: id5KeyDown,
        id6KeyDown: id6KeyDown,
        classpathKeyDown: classpathKeyDown,
        floatKeyDown: floatKeyDown,
        minusKeyDown: minusKeyDown
      };
    }
  ]);
})(angular);
